package com.lw.lwte.common.helper;

import cn.hutool.core.io.FileUtil;
import com.lw.lwte.common.enums.OsType;
import com.lw.lwte.common.util.OsInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.testng.annotations.Test;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Slf4j
public class FileHelper extends FileUtils {

    private static final String ENCODING = "UTF-8";

    private FileHelper() {
    }

    /**
     * 验证文件是否存在并且不为空
     *
     * @param file 要验证的文件
     */
    private static void validate(File file) {
        AssertHelper.notNull(file, "file can't be null");
        AssertHelper.isTrue(file.exists(), "file not exists: " + file.getAbsolutePath());
    }

    /**
     * 检查文件夹是否存在
     *
     * @param path 要检查的文件夹路径
     * @return 如果文件夹存在则返回true，否则返回false
     */
    public static boolean checkDirectoryExist(String path) {
        File file = new File(path);
        if (file.exists()) {
            return file.isDirectory();
        }

        return false;
    }

    /**
     * 检查文件是否存在
     *
     * @param path 要检查的文件路径
     * @return 如果文件存在则返回true，否则返回false
     */
    public static boolean checkFileExist(String path) {
        File file = new File(path);
        if (file.exists()) {
            return file.isFile();
        }

        return false;
    }

    /**
     * 检查文件夹是否存在，不存在则创建
     *
     * @param path
     */
    public static void createDirectory(String path) {
        File file = new File(path);
        if (file.exists()) {
            if (file.isDirectory()) {
                log.debug(String.format("Directory [%s] existed.", path));
            } else {
                log.debug(String.format("File [%s] existed, cannot create the same name file.", path));
            }
        } else {
            log.debug("Create directory: " + path);
            file.mkdirs();
        }
    }

    /**
     * 读取文件为字符串 (UTF-8模式读取)
     *
     * @param file
     * @throws IOException
     */
    public static String readToString(File file) {
        validate(file);
        return FileUtil.readString(file, Charset.forName(ENCODING));
    }

    /**
     * 读取指定路径的文件内容，并返回其内容作为字符串。
     *
     * @param path 文件的路径
     * @return 文件内容的字符串表示，如果文件不存在或路径错误，则返回空字符串
     */
    public static String readText(String path) {
        StringBuilder text = new StringBuilder();
        File file = new File(path);
        if (file.isFile() && file.exists()) {
            String line = null;
            try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)))) {
                while ((line = br.readLine()) != null) {
                    text.append(line.trim());
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            log.error("Cannot find file: " + path);
        }

        return text.toString();
    }

    /**
     * 将输入流转换为字符串
     *
     * @param stream 输入流对象
     * @return 字符串形式的输入流内容，如果读取失败则返回null
     */
    public static String readStreamToString(InputStream stream) {
        StringBuffer sb = new StringBuffer();
        try {
            int index = 0;
            byte[] b = new byte[1024];
            while ((index = stream.read(b)) != -1) {
                sb.append(new String(b, 0, index, Charset.forName(ENCODING)));
            }
            return sb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stream != null) {
                    stream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 处理Windows路径带"/"问题
     *
     * @param path 待处理的路径字符串
     * @return 处理后的路径字符串，如果是Windows系统且路径以"/"开头，则去掉"/"，否则直接返回原路径
     */
    public static String resolveResourcePath(String path) {
        OsType osType = OsInfo.getOsType();
        if (osType == OsType.Windows) {
            if (path == null) {
                return path;
            }
            //如果是以"/"开头，则去掉
            if (path.startsWith("/")) {
                return path.substring(1);
            }
        }

        return path;
    }

    /**
     * 读取文件为字符串列表（UTF-8模式读取）
     *
     * @param file 需要读取的文件对象
     * @return 文件内容的字符串列表
     * @throws IOException 如果读取文件过程中发生IO异常
     */
    public static List<String> readFileToStringList(File file) throws IOException {
        return readFileToStringList(file, ENCODING);
    }

    /**
     * 读取文件为字符串列表
     *
     * @param file
     * @param encoding
     * @throws IOException
     */
    public static List<String> readFileToStringList(File file, String encoding) {
        validate(file);
        List<String> list = new ArrayList<>();
        try {
            LineIterator lineIterator = FileUtils.lineIterator(file, encoding);
            while (lineIterator.hasNext()) {
                list.add(lineIterator.nextLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return list;
    }

    public static String getNameWithoutSuffix(File file) {
        String fileName = file.getName();
        return getNameWithoutSuffix(fileName);
    }

    public static String getNameWithoutSuffix(String filePath) {
        String fileName;
        if (filePath.contains("\\")) {
            fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
        } else if (filePath.contains("/")) {
            fileName = filePath.substring(filePath.lastIndexOf("/") + 1);
        }else{
            fileName = filePath;
        }
        return fileName.substring(0, fileName.lastIndexOf("."));
    }

    /**
     * 获取扩展名
     *
     * @param file
     */
    public static String getExtension(File file) {
        if (Objects.isNull(file)) {
            return null;
        }
        return getExtension(file.getName());
    }

    /**
     * 获取扩展名
     *
     * @param filePath
     */
    public static String getExtension(String filePath) {
        return filePath.substring(filePath.lastIndexOf(".") + 1);
    }

    /**
     * 文件路径拼接
     *
     * @param base
     * @param params
     * @return
     */
    public static String combine(String base, String... params) {
        String path = base;
        if (params != null) {
            for (String item : params) {
                path += File.separator + item;
            }
        }

        return path;
    }

    public static String searchFirstFile(String baseDir, String fileName, String extension){
        File dirFile = new File(baseDir);
        if(!dirFile.exists()){
            log.error("Directory [{}] not exist.", baseDir);
            return StringHelper.EMPTY;
        } else {
            String searchFile = fileName;
            if(extension != null){
                searchFile += extension;
            }
            String finalSearchFile = searchFile;

            File[] files = dirFile.listFiles(pathname -> !pathname.isDirectory());
            Optional<File> resultOpt = Arrays.stream(files).filter(o->o.getName().equals(finalSearchFile)).findFirst();
            if(resultOpt.isPresent()){
                return resultOpt.get().getAbsolutePath();
            }

            File[] dirs = dirFile.listFiles(pathname -> pathname.isDirectory());
            for(File file : dirs){
                String result = searchFirstFile(file.getAbsolutePath(), fileName, extension);
                if(StringHelper.isNullOrBlank(result)){
                    continue;
                } else {
                    return result;
                }
            }

            return StringHelper.EMPTY;
        }
    }

    @Test
    public void combinePathTest() {
        String path1 = combine("D:\\Test");
        String path2 = combine("D:\\Test", "mess");
        String path3 = combine("D:\\Test", "mess", "test");
        System.out.println(path1);
        System.out.println(path2);
        System.out.println(path3);
    }

    @Test
    public void fileNameTest() {
        String filePath = "D:\\Mess\\code\\test_HTMLTestRunner.py";
        File file = new File(filePath);
        System.out.println(getNameWithoutSuffix(filePath));
        System.out.println(getNameWithoutSuffix(file));
    }

    @Test
    public void searchSqlFileTest() {
        String basePath = "D:\\GiteeCode\\looneasy-products\\loongeasy-cloud\\docs\\sql";
        System.out.println(searchFirstFile(basePath, "1.2.0-mysql-all.sql", null));
        System.out.println(searchFirstFile(basePath, "1.2.5-mysql-hx-standard", ".sql"));
        System.out.println(searchFirstFile(basePath, "1.3.0-gauss-hx-standard", ".sql"));
    }
}
